package com.jsjvm.client.dbg;


/**
 * The front-end identifies objects by "ID"s, so we must be able to retrieve
 * objects by ID, and to associate to each object an ID. 
 * 
 * @author ctalau
 *
 */
public class ObjectIDManager {
	private static final int TABLE_SIZE = 1024;
	private IDIdentifiable objTable[] = new IDIdentifiable[TABLE_SIZE];
	private int pos = 0;

	private ObjectIDManager() {
		objTable[0] = null;
		objTable[1] = new SimpleIDIdentifiable(1); // thread id
		objTable[2] = new SimpleIDIdentifiable(2); // thread group id
		objTable[3] = new SimpleIDIdentifiable(3); // class loader id
	}
	
	private static ObjectIDManager inst = new ObjectIDManager();
	public static ObjectIDManager getInstance() {
		return inst;
	}

	/**
	 * Retrieves an object by it's ID. When front-end passes parameters.
	 */
	public Object getObjectByID(int id) {
		return objTable[id];
	}

	/**
	 * Destroys the reference to the object making it available to garbage collection. 
	 */
	public void disposeObject(int id) {
		if (objTable[id] != null)
			objTable[id].setID(-1);
		objTable[id] = null;
	}

	/**
	 * The object is assigned an ID (if it doesn't have one already)
	 */
	public int assignObjectID(IDIdentifiable obj) {
		if (obj.getID() > 0)
			return obj.getID();

		// inefficiently search for a free location in the table
		int cnt = 0;
		while (objTable[pos] != null && cnt < TABLE_SIZE) {
			pos = (pos + 1) % TABLE_SIZE;
			cnt++;
		}

		if (cnt == TABLE_SIZE) {
			System.out.println("Need garbage collection!");
		}

		obj.setID(pos);
		objTable[pos] = obj;

		return pos++;
	}

	/**
	 * Interface implemented by each member which can be passed to the front-end
	 * 
	 * @author ctalau
	 *
	 */
	public static interface IDIdentifiable {
		// a value greater than 0, means a valid ID
		public int getID();

		public void setID(int id);
	}

	/**
	 * Simple implementation of the above interface.
	 * 
	 * @author ctalau
	 *
	 */
	public static class SimpleIDIdentifiable implements IDIdentifiable {
		private int id = -1;

		public SimpleIDIdentifiable() {
		}

		public SimpleIDIdentifiable(int id) {
			this.id = id;
		}

		@Override
		public int getID() {
			return id;
		}

		@Override
		public void setID(int id) {
			this.id = id;
		}
	}
}
